package com.nanjia.boot.product.category.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nanjia.boot.common.enums.StatusEnum;
import com.nanjia.boot.common.model.Option;
import com.nanjia.boot.core.security.util.SecurityUtils;
import com.nanjia.boot.product.category.converter.ProductCategoryConverter;
import com.nanjia.boot.product.category.mapper.ProductCategoryMapper;
import com.nanjia.boot.product.category.model.entity.ProductCategory;
import com.nanjia.boot.product.category.model.form.ProductCategoryForm;
import com.nanjia.boot.product.category.model.query.ProductCategoryQuery;
import com.nanjia.boot.product.category.model.vo.ProductCategoryVO;
import com.nanjia.boot.product.category.service.ProductCategoryService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 商品分类服务实现类
 *
 * @author 周洋
 * @since 2025-07-04 15:24
 */
@Service
@RequiredArgsConstructor
public class ProductCategoryServiceImpl extends ServiceImpl<ProductCategoryMapper, ProductCategory> implements ProductCategoryService {

    private final ProductCategoryConverter productCategoryConverter;

    /**
     * 获取商品分类分页列表
     *
     * @param queryParams 查询参数
     * @return {@link IPage<ProductCategoryVO>} 商品分类分页列表
     */
    @Override
    public IPage<ProductCategoryVO> getProductCategoryPage(ProductCategoryQuery queryParams) {
        return this.baseMapper.getProductCategoryPage(
                new Page<>(queryParams.getPageNum(), queryParams.getPageSize()),
                queryParams
        );
    }

    /**
     * 获取商品分类表单数据
     *
     * @param id 商品分类ID
     * @return 商品分类表单数据
     */
    @Override
    public ProductCategoryForm getProductCategoryFormData(Long id) {
        ProductCategory entity = this.getById(id);
        return productCategoryConverter.toForm(entity);
    }

    /**
     * 新增商品分类
     *
     * @param formData 商品分类表单对象
     * @param ipAddr
     * @return 是否新增成功
     */
    @Override
    public boolean saveProductCategory(ProductCategoryForm formData, String ipAddr) {

        LambdaQueryWrapper<ProductCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(ProductCategory::getId);
        List<ProductCategory> list = this.list(queryWrapper);
        int x = 0;
        if (CollectionUtils.isNotEmpty(list)) {
            x = Integer.parseInt(list.get(0).getCategoryCode());
        }
        ProductCategory entity = productCategoryConverter.toEntity(formData);
        entity.setCategoryCode(String.format("%04d", x + 1));
        entity.setCreateBy(SecurityUtils.getUserStrId());
        entity.setCreateIp(ipAddr);
        entity.setCreateTime(LocalDateTime.now());
        return this.save(entity);
    }

    /**
     * 更新商品分类
     *
     * @param id       商品分类ID
     * @param formData 商品分类表单对象
     * @param ipAddr
     * @return 是否修改成功
     */
    @Override
    public boolean updateProductCategory(Long id, ProductCategoryForm formData, String ipAddr) {
        ProductCategory entity = productCategoryConverter.toEntity(formData);
        entity.setId(id);
        entity.setUpdateBy(JSONUtil.toJsonStr(SecurityUtils.getUserId()));
        entity.setUpdateIp(ipAddr);
        entity.setUpdateTime(LocalDateTime.now());
        return this.updateById(entity);
    }

    /**
     * 删除商品分类
     *
     * @param ids    商品分类ID，多个以英文逗号(,)分割
     * @param ipAddr 修改地址
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteProductCategorys(String ids, String ipAddr) {
        Assert.isTrue(StrUtil.isNotBlank(ids), "删除的商品分类数据为空");
        // 逻辑删除
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(Long::parseLong)
                .toList();
        List<ProductCategory> list = new ArrayList<>();
        for (Long l : idList) {
            ProductCategory entity = new ProductCategory();
            entity.setId(l);
            entity.setCategoryStatus(StatusEnum.DELETE.getValue());
            entity.setUpdateBy(JSONUtil.toJsonStr(SecurityUtils.getUserId()));
            entity.setUpdateTime(LocalDateTime.now());
            entity.setUpdateIp(ipAddr);
            list.add(entity);
        }
        return this.updateBatchById(list, list.size());
    }


    @Override
    public List<ProductCategoryVO> getProductCategoryList(ProductCategoryQuery queryParams) {


        // 查询数据
        List<ProductCategory> productCategoryList = this.list(
                new LambdaQueryWrapper<ProductCategory>()
                        .like(StrUtil.isNotBlank(queryParams.getCategoryCode()), ProductCategory::getCategoryCode, queryParams.getCategoryCode())
                        .like(StrUtil.isNotBlank(queryParams.getCategoryName()), ProductCategory::getCategoryCode, queryParams.getCategoryName())
                        .eq(queryParams.getCategoryStatus() != null, ProductCategory::getCategoryStatus, queryParams.getCategoryStatus())
                        .orderByDesc(ProductCategory::getId)
        );

        if (CollectionUtil.isEmpty(productCategoryList)) {
            return Collections.EMPTY_LIST;
        }

        // 获取所有部门ID
        Collection<Long> deptIds = productCategoryList.stream()
                .map(ProductCategory::getId)
                .collect(Collectors.toSet());
        // 获取父节点ID
        Set<Long> parentIds = productCategoryList.stream()
                .map(ProductCategory::getParentId)
                .collect(Collectors.toSet());
        // 获取根节点ID（递归的起点），即父节点ID中不包含在部门ID中的节点，注意这里不能拿顶级部门 O 作为根节点，因为部门筛选的时候 O 会被过滤掉
        List<Long> rootIds = CollectionUtil.subtractToList(parentIds, deptIds);

        // 递归生成部门树形列表
        return rootIds.stream()
                .flatMap(rootId -> recurProductCategoryList(rootId, productCategoryList).stream())
                .toList();
    }

    /**
     * 递归生成形列表
     *
     * @param parentId            父ID
     * @param productCategoryList 列表
     * @return 树形列表
     */
    public List<ProductCategoryVO> recurProductCategoryList(Long parentId, List<ProductCategory> productCategoryList) {
        return productCategoryList.stream()
                .filter(productCategory -> productCategory.getParentId().equals(parentId))
                .map(productCategory -> {
                    ProductCategoryVO productCategoryVO = productCategoryConverter.toVo(productCategory);
                    List<ProductCategoryVO> children = recurProductCategoryList(productCategory.getId(), productCategoryList);
                    productCategoryVO.setChildren(children);
                    return productCategoryVO;
                }).toList();
    }

    @Override
    public List<Option<Long>> listProductCategoryOptions() {
        List<ProductCategory> productCategoryList = this.list(new LambdaQueryWrapper<ProductCategory>()
                .eq(ProductCategory::getCategoryStatus, StatusEnum.ENABLE.getValue())
                .select(ProductCategory::getId, ProductCategory::getParentId, ProductCategory::getCategoryName)
                .orderByDesc(ProductCategory::getId)
        );
        if (CollectionUtil.isEmpty(productCategoryList)) {
            return Collections.EMPTY_LIST;
        }

        Set<Long> deptIds = productCategoryList.stream()
                .map(ProductCategory::getId)
                .collect(Collectors.toSet());

        Set<Long> parentIds = productCategoryList.stream()
                .map(ProductCategory::getParentId)
                .collect(Collectors.toSet());

        List<Long> rootIds = CollectionUtil.subtractToList(parentIds, deptIds);

        // 递归生成部门树形列表
        return rootIds.stream()
                .flatMap(rootId -> recurProductCategoryTreeOptions(rootId, productCategoryList).stream())
                .toList();
    }

    private List<Option<Long>> recurProductCategoryTreeOptions(Long parentId, List<ProductCategory> productCategoryList) {

        return CollectionUtil.emptyIfNull(productCategoryList).stream()
                .filter(productCategory -> productCategory.getParentId().equals(parentId))
                .map(productCategory -> {
                    Option<Long> option = new Option<>(productCategory.getId(), productCategory.getCategoryName());
                    List<Option<Long>> children = recurProductCategoryTreeOptions(productCategory.getId(), productCategoryList);
                    if (CollectionUtil.isNotEmpty(children)) {
                        option.setChildren(children);
                    }
                    return option;
                })
                .collect(Collectors.toList());

    }
}
